//=======================================================================//
//= Include files.													    =//
//=======================================================================//
#include <wx/filedlg.h>
#include <wx/msgdlg.h>
#include "ImageToolWindow.h"
#include "ControlID.h"
#include "ResizeDialog.h"
#include "Settings.h"
#include "Encoder.h"
#include "Utility.h"
#include "WorkThread.h"

//=======================================================================//
//= Global variable define.											    =//
//=======================================================================//
const wxString PIXEL_IMAGE_WINDOW_NAME = wxT("Image Window");

//=======================================================================//
//= Event table.													    =//
//=======================================================================//
BEGIN_EVENT_TABLE(ImageToolWindow, sptChildWindowBase)
	EVT_GLOBAL_SETTINGS(EVT_SETTING_CHANGED, ImageToolWindow::OnSettingChanged)
	EVT_TOOL(ID_TOOL_IMAGE_RESIZE,			ImageToolWindow::OnResize)
	EVT_TOOL(ID_TOOL_IMAGE_NEW,				ImageToolWindow::OnNewImage)
END_EVENT_TABLE()

//=======================================================================//
//= Function define.										            =//
//=======================================================================//
ImageToolWindow::ImageToolWindow(wxWindow* pclsParent)
: sptChildWindowBase(pclsParent, wxID_ANY)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	_create();
	/* Layout window. */
	Layout();
}

ImageToolWindow::ImageToolWindow(wxWindow* pclsParent, const wxSize& clsImageSize)
: sptChildWindowBase(pclsParent, wxID_ANY)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	_create();
	/* Create paint panel. */
	m_pclsPicPaintCtrl = new PicturePaintCtrl(m_pclsWorkingPanel, wxID_ANY, clsImageSize);
	/* Set configuration. */
	_configPaintPantl();
	m_pclsPicPaintCtrl->CleanScreen();
	m_pclsPicPaintCtrl->FitBestSize();
	/* Layout window. */
	Layout();
}

ImageToolWindow::ImageToolWindow(wxWindow* pclsParent, const wxString& cstrFilePath)
: sptChildWindowBase(pclsParent, wxID_ANY, cstrFilePath)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	_create();
	if(wxFileName::Exists(cstrFilePath))
	{
		OpenFile(cstrFilePath);
	}

	Layout();
}

ImageToolWindow::~ImageToolWindow()
{

}

void ImageToolWindow::_create(void)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxBoxSizer*				pclsRootSizer = new wxBoxSizer(wxVERTICAL);
	wxBoxSizer*				pclsPaintSizer = new wxBoxSizer(wxHORIZONTAL);
	wxBoxSizer*				pclsDataSizer = new wxBoxSizer(wxHORIZONTAL);
	wxToolBar*				pclsToolBar = _createToolsBar();

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	m_pclsWorkingPanel = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE|wxHSCROLL|wxVSCROLL );
	m_pclsWorkingPanel->SetScrollRate( 5, 5 );

	/* Initialize paint panel object pointer. */
	m_pclsPicPaintCtrl = nullptr;

	pclsPaintSizer->Add(pclsToolBar, 0, wxEXPAND, 1);
	pclsPaintSizer->Add(m_pclsWorkingPanel, 1, wxEXPAND, 1);
	pclsRootSizer->Add(pclsPaintSizer, 1, wxEXPAND, 1);
	pclsRootSizer->Add(pclsDataSizer, 0, wxEXPAND, 5);

	SetSizer( pclsRootSizer );

	pclsToolBar->Realize();
}

wxToolBar* ImageToolWindow::_createToolsBar(void)
{
    /*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxToolBar*				pclsToolBar = nullptr;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	// Create tool bar.
	pclsToolBar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_LEFT);
	pclsToolBar->AddTool(ID_TOOL_IMAGE_NEW, wxT("New"), wxBITMAP_PNG(RES_ID_TOOL_IMAGE_NEW_IMAGE), wxNullBitmap, wxITEM_NORMAL, wxT("New"), wxT("Create new image."));
	pclsToolBar->AddTool(ID_TOOL_IMAGE_RESIZE, wxT("Resize"), wxBITMAP_PNG(RES_ID_TOOL_IMAGE_RESIZE_IMAGE), wxNullBitmap, wxITEM_NORMAL, wxT("Resize"), wxT("Resize edit area."));
	pclsToolBar->AddSeparator();
	// Font size spin.
	pclsToolBar->AddTool(ID_TOOL_IMAGE_POINT, wxT("Point"), wxBITMAP_PNG(RES_ID_TOOL_IMAGE_PAINT_POINT), wxNullBitmap, wxITEM_RADIO, wxT("Point"), wxT("Paint point."));
	//pclsToolBar->AddTool(ID_TOOL_IMAGE_PAINT_LINE, wxT("Line"), wxBITMAP_PNG(RES_ID_TOOL_IMAGE_PAINT_LINE), wxNullBitmap, wxITEM_RADIO, wxT("Line"), wxT("Paint line."));
	//pclsToolBar->AddTool(ID_TOOL_IMAGE_PAINT_RECT, wxT("Rectangle"), wxBITMAP_PNG(RES_ID_TOOL_IMAGE_PAINT_RECT), wxNullBitmap, wxITEM_RADIO, wxT("Rectangle"), wxT("Paint rectangle."));
	//pclsToolBar->AddTool(ID_TOOL_IMAGE_PAINT_CIR, wxT("Circle"), wxBITMAP_PNG(RES_ID_TOOL_IMAGE_PAINT_CIRCLE), wxNullBitmap, wxITEM_RADIO, wxT("Circle"), wxT("Paint circle."));

	return pclsToolBar;
}

void ImageToolWindow::_configPaintPantl(void)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(nullptr != m_pclsPicPaintCtrl)
	{
		wxLogInfo(wxT("Paint panel initializing."));
		m_pclsPicPaintCtrl->SetGridColor(ConfigurationInstance().PanelConfiguration().GetGridColour());
		m_pclsPicPaintCtrl->SetPanelColour(ConfigurationInstance().PanelConfiguration().GetBackgroundColour(), false);
		m_pclsPicPaintCtrl->SetPixelColour(ConfigurationInstance().PanelConfiguration().GetForegroundColour(), false);
		wxLogInfo(wxT("Panel colour is 0x%08X."), ConfigurationInstance().PanelConfiguration().GetBackgroundColour().GetRGB());
		wxLogInfo(wxT("Pixel colour is 0x%08X."), ConfigurationInstance().PanelConfiguration().GetForegroundColour().GetRGB());
		wxLogInfo(wxT("Grid colour is 0x%08X."), ConfigurationInstance().PanelConfiguration().GetGridColour().GetRGB());
		wxLogInfo(wxT("Paint panel initialized."));
	}
}

void ImageToolWindow::OnFontChanged(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	/* Do nothing. */
	clsEvent.StopPropagation();
}

void ImageToolWindow::OnSettingChanged(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(nullptr != m_pclsPicPaintCtrl)
	{
		m_pclsPicPaintCtrl->SetGridColor(ConfigurationInstance().PanelConfiguration().GetGridColour());
		m_pclsPicPaintCtrl->SetPanelColour(ConfigurationInstance().PanelConfiguration().GetBackgroundColour(), false);
		m_pclsPicPaintCtrl->SetPixelColour(ConfigurationInstance().PanelConfiguration().GetForegroundColour(), true);
	}
	clsEvent.StopPropagation();
}

void ImageToolWindow::OnNewImage(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	ResizeDialog			clsResizeDialog(this);
	int						iWidthInPixel, iHeightInPixel;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	clsResizeDialog.SetSizeValue(wxSize(128, 64));

    if(wxID_OK == clsResizeDialog.ShowModal())
    {
    	iWidthInPixel = clsResizeDialog.GetSizeValue().GetWidth();
    	iHeightInPixel = clsResizeDialog.GetSizeValue().GetHeight();

    	if(nullptr == m_pclsPicPaintCtrl)
		{
			m_pclsPicPaintCtrl = new PicturePaintCtrl(m_pclsWorkingPanel, wxID_ANY, clsResizeDialog.GetSizeValue());
		}
		else
		{
			m_pclsPicPaintCtrl->SetPixelNumber(iWidthInPixel, iHeightInPixel);
		}
		m_pclsPicPaintCtrl->CleanScreen();
		m_pclsPicPaintCtrl->FitBestSize();
		m_pclsWorkingPanel->SetVirtualSize(m_pclsPicPaintCtrl->GetBestSize());
		_configPaintPantl();
		m_pclsPicPaintCtrl->RefreshDisplay();
    }

	clsEvent.Skip();
	clsEvent.StopPropagation();
}

void ImageToolWindow::OnOpenImage(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxFileDialog			clsOpenFileDialog(this, wxT("Open image file."), wxEmptyString, wxEmptyString,
										wxT("Bitmap file (*.bmp)|*.bmp|All files (*.*)|*.*"), wxFD_OPEN|wxFD_FILE_MUST_EXIST);
	wxString				strFileName;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
    if(wxID_OK == clsOpenFileDialog.ShowModal())
    {
    	strFileName = clsOpenFileDialog.GetPath();
    	if(nullptr == m_pclsPicPaintCtrl)
		{
			m_pclsPicPaintCtrl = new PicturePaintCtrl(m_pclsWorkingPanel, wxID_ANY);
			_configPaintPantl();
		}
    	if(false == m_pclsPicPaintCtrl->LoadBmpFile(strFileName))
		{
			wxMessageBox(wxT("Open bitmap failed."), wxT("Error"), wxOK|wxICON_ERROR);
		}
    }
	clsEvent.Skip();
	clsEvent.StopPropagation();
}

void ImageToolWindow::OnResize(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	ResizeDialog			clsResizeDialog(this);
	int						iWidthInPixel, iHeightInPixel;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	m_pclsPicPaintCtrl->GetPixelNumber(&iWidthInPixel, &iHeightInPixel);
	clsResizeDialog.SetSizeValue(wxSize(iWidthInPixel, iHeightInPixel));

    if(wxID_OK == clsResizeDialog.ShowModal())
    {
    	iWidthInPixel = clsResizeDialog.GetSizeValue().GetWidth();
    	iHeightInPixel = clsResizeDialog.GetSizeValue().GetHeight();
    	m_pclsPicPaintCtrl->SetPixelNumber(iWidthInPixel, iHeightInPixel);
    	m_pclsPicPaintCtrl->FitBestSize();
    }

	clsEvent.Skip();
	clsEvent.StopPropagation();
}

bool ImageToolWindow::StartProcess(wxEvtHandler* pclsEventHandler)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	return WorkThreadMgr::Instance(ID_WORK_THREAD).StartThread(pclsEventHandler, ImageWorkThread::New(m_pclsPicPaintCtrl->AsBitmap().ConvertToImage()));
}

bool ImageToolWindow::OpenFile(void)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxFileDialog			clsOpenFileDialog(this, wxT("Open image file."), wxEmptyString, wxEmptyString,
										wxT("Bitmap file (*.bmp)|*.bmp|All files (*.*)|*.*"), wxFD_OPEN|wxFD_FILE_MUST_EXIST);
	bool					bReturn = false;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
    if(wxID_OK == clsOpenFileDialog.ShowModal())
    {
    	bReturn = OpenFile(clsOpenFileDialog.GetPath());
    }

    return bReturn;
}

bool ImageToolWindow::OpenFile(const wxString& cstrPath)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	bool					bReturn = true;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(nullptr == m_pclsPicPaintCtrl)
	{
		m_pclsPicPaintCtrl = new PicturePaintCtrl(m_pclsWorkingPanel, wxID_ANY);
		_configPaintPantl();
	}
	if(m_pclsPicPaintCtrl->LoadBmpFile(cstrPath))
	{
		SetFilePath(cstrPath);
	}
	else
	{
		wxMessageBox(wxT("Open bitmap failed."), wxT("Error"), wxOK|wxICON_ERROR);
		bReturn = false;
	}

	return bReturn;
}

bool ImageToolWindow::SaveFile(void)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxFileDialog			clsSaveFileDialog(this, wxT("Save to file."), wxEmptyString, wxEmptyString,
										wxT("Bitmap file (*.bmp)|*.bmp|All files (*.*)|*.*"), wxFD_SAVE);
	bool					bReturn;
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
    if(wxID_OK == clsSaveFileDialog.ShowModal())
    {
    	bReturn = m_pclsPicPaintCtrl->AsBitmap().SaveFile(clsSaveFileDialog.GetPath(), wxBITMAP_TYPE_BMP);
    	SetFilePath(clsSaveFileDialog.GetPath());
    }
    else
	{
		bReturn = false;
	}

	return bReturn;
}
